home *** CD-ROM | disk | FTP | other *** search
/ Mac Mania 5 / MacMania 5.toast / / Internet software / Analog 2.0 / Analog 2.0 Src / utils.c < prev   
Text File  |  1997-02-12  |  14KB  |  593 lines

  1. /*** analog 2.0 ***/
  2. /* Please read Readme.html, or http://www.statslab.cam.ac.uk/~sret1/analog/  */
  3.  
  4. /*** utils.c; lots of little functions to do odd little things ***/
  5.  
  6. #include "analhea2.h"
  7.  
  8. /* First, wildcard matching. */
  9.  
  10. flag matchq(char *string, char *pattern, flag whole)
  11. {        /* Match with no *'s, whole or start of string against pattern */
  12.   flag answer;
  13.  
  14.   for (answer = TRUE; answer == TRUE && *pattern != '\0' ; ) {
  15.     answer = (*string == *pattern || *pattern == '?') && (*string != '\0');
  16.     string++;
  17.     pattern++;
  18.   }
  19.  
  20.   if (whole && *string != '\0')
  21.     return(FALSE);
  22.  
  23.   return(answer);
  24. }
  25.  
  26. flag wildmatch(char *string, char *pattern, char **w1, char **w2)
  27. {   /* w1 and &w2 changed to reflect part of string represented by final *   */
  28.   char *c;
  29.   flag matched;
  30.   int len;
  31.   char tempstr[MAXSTRINGLENGTH];
  32.   flag tempflag;
  33.  
  34.   strcpy(tempstr, pattern);   /* so pattern won't be destroyed by strtok */
  35.  
  36.   if ((c = strrchr(tempstr, '*')) == NULL) {   /* no *'s */
  37.     *w1 = string;
  38.     *w2 = string;
  39.     return(matchq(string, pattern, TRUE));
  40.   }
  41.   else {
  42.     *w2 = string + MAX(strlen(string) - strlen(c + 1), 0);
  43.     if (!matchq(*w2, c + 1, TRUE))      /* if tail portions don't match */
  44.       return(0);
  45.     *c = '\0';   /* o/wise we'll end up matching the tail twice */
  46.     c = strtok(tempstr, "*");
  47.     if (pattern[0] == '*') {   /* don't need to match against beginning */
  48.       tempflag = ON;
  49.       *w1 = string;
  50.     }
  51.     else {
  52.       tempflag = OFF;
  53.       if (matchq(string, c, FALSE) == FALSE)
  54.     return(FALSE);    /* check first bit matches beginning of string */
  55.       *w1 = string + strlen(c); /* w1 measures where we're up to in string */
  56.       if (*w1 > *w2)
  57.     return(FALSE);   /* start and end of pattern overlapped in string */
  58.     }
  59.     if (tempflag && c == NULL)
  60.       return(TRUE);  /* this only occurs with patterns like "*nomorestars" */
  61.     else while (tempflag || ((c = strtok((char *)NULL, "*")) != NULL)) {
  62.       /* if tempflag, c is already set to after initial *  */
  63.       tempflag = OFF;
  64.       matched = FALSE;
  65.       len = strlen(c);
  66.       while (*w1 + len <= *w2 && matched == FALSE) {
  67.     if (matchq(*w1, c, FALSE) == TRUE)
  68.       matched = TRUE;
  69.     else
  70.       (*w1)++;
  71.       }
  72.       if (!matched)
  73.     return(FALSE);
  74.       else
  75.     *w1 += len;
  76.     }
  77.     return(TRUE);  /* if got this far, matched everything */
  78.   }
  79. }
  80.  
  81. int strtomonth(char month[4])  /* convert 3 letter month abbrev. to int */
  82. {
  83.   int monthno = ERR;
  84.  
  85.   switch (month[0]) {
  86.   case 'A':
  87.     switch (month[1]) {
  88.     case 'p':
  89.       monthno = 3;
  90.       break;
  91.     case 'u':
  92.       monthno = 7;
  93.       break;
  94.     }
  95.     break;
  96.     case 'D':
  97.     monthno = 11;
  98.       break;
  99.   case 'F':
  100.     monthno = 1;
  101.     break;
  102.     case 'J':
  103.     switch (month[1]) {
  104.     case 'a':
  105.       monthno = 0;
  106.       break;
  107.     case 'u':
  108.       switch (month[2]) {
  109.       case 'l':
  110.     monthno = 6;
  111.     break;
  112.       case 'n':
  113.     monthno = 5;
  114.     break;
  115.       }
  116.       break;
  117.     }
  118.     break;
  119.   case 'M':
  120.     switch (month[2]) {
  121.     case 'r':
  122.       monthno = 2;
  123.       break;
  124.     case 'y':
  125.       monthno = 4;
  126.       break;
  127.     }
  128.     break;
  129.   case 'N':
  130.     monthno = 10;
  131.     break;
  132.   case 'O':
  133.     monthno = 9;
  134.       break;
  135.   case 'S':
  136.     monthno = 8;
  137.     break;
  138.   }
  139.  
  140.   return(monthno);
  141.  
  142. }
  143.  
  144. int dayofdate(int date, int monthno, int year)  /* day of week of given date */
  145. {
  146.   extern int dateoffset[];
  147.  
  148.   int x;
  149.   x = dateoffset[monthno] + date + year + (year / 4) + 5 -
  150.     ISLEAPJF(monthno, year);
  151.   return(x % 7);
  152. }
  153.  
  154. int minsbetween(int date1, int monthno1, int year1, int hr1, int min1,
  155.         int date2, int monthno2, int year2, int hr2, int min2)
  156. {
  157.   extern int dateoffset[];
  158.  
  159.   int x, y;
  160.   x = dateoffset[monthno1] + date1 + year1 * 365 + (year1 / 4) -
  161.     ISLEAPJF(monthno1, year1);
  162.   y = dateoffset[monthno2] + date2 + year2 * 365 + (year2 / 4) -
  163.     ISLEAPJF(monthno2, year2);
  164.  
  165.   return((y - x) * 1440 + (hr2 - hr1) * 60 + (min2 - min1));
  166. }
  167.  
  168. long timecode(int date, int monthno, int year, int hr, int min)
  169. {   /* calculate a 'timecode', i.e. increasing function of time */
  170.  
  171.   return((year - 1990) * 535680 +       /* 60 * 24 * 31 * 12 */
  172.      monthno * 44640 +
  173.      date * 1440 +
  174.      hr * 60 +
  175.      min);
  176. }
  177.  
  178. struct timestruct startofweek(struct timestruct atime)
  179. {  /* given a time, what is the time at the start of that week? */
  180.  
  181.   extern int monthlength[];
  182.  
  183.   extern int weekbeginson;
  184.  
  185.   struct timestruct answer;
  186.   int day;
  187.   
  188.   day = dayofdate(atime.date, atime.monthno, atime.year);
  189.  
  190.   answer.date = atime.date - day + weekbeginson;
  191.            /* giving a weekbeginson-day in [date - 6, date + 6] */
  192.   if (answer.date > atime.date)
  193.     answer.date -= 7;
  194.   answer.monthno = atime.monthno;
  195.   answer.year = atime.year;
  196.  
  197.   if (answer.date <= 0) {
  198.     answer.monthno--;
  199.     if (answer.monthno == -1) {
  200.       answer.monthno = 11;
  201.       answer.year--;
  202.     }
  203.     answer.date = monthlength[answer.monthno] + answer.date +
  204.       ISLEAPFEB(answer.monthno, answer.year);
  205.   }
  206.  
  207.   answer.code = timecode(answer.date, answer.monthno, answer.year,
  208.              answer.hr = 0, answer.min = 0);
  209.  
  210.   return(answer);
  211.  
  212. }
  213.  
  214. FILE *fopenlog(char *name, char logtype[12], flag *ispipe)
  215. {             /* open a logfile with a particular name for reading */
  216. #ifndef NOPIPES
  217.   extern FILE *popen();
  218. #endif
  219.  
  220.   extern char *commandname;
  221. #ifndef NOPIPES
  222.   extern struct loglist *uncompresshead;
  223. #endif
  224.   extern flag warnq, anywarns, stdin_used;
  225.   extern int debug;
  226.  
  227.   FILE *f;
  228. #ifndef NOPIPES
  229.   struct loglist *uncompressp;
  230.   char *w1, *w2;
  231.   char command[MAXSTRINGLENGTH];
  232. #endif
  233.  
  234.   *ispipe = OFF;
  235.  
  236.   if (STREQ(name, "stdin") || STREQ(name, "-")) {
  237.     if (stdin_used) {
  238.       if (warnq) {
  239.     fprintf(stderr,
  240.         "%s: Warning: stdin already used; cannot use it as %s\n",
  241.         commandname, logtype);
  242.     anywarns = ON;
  243.       }
  244.     }
  245.     else {
  246.       f = stdin;
  247.       stdin_used = ON;
  248.       if (debug > 0)
  249.     fprintf(stderr, "F: Opening stdin as %s\n", logtype);
  250.     }
  251.   }
  252.   else {
  253. #ifdef VMS
  254.     f = fopen(name, "r", "shr=upd");
  255. #else
  256.     f = fopen(name, "r");
  257. #endif
  258.     if (f == NULL) {
  259.       if (warnq) {
  260.     fprintf(stderr, "%s: Warning: Failed to open %s %s: ignoring it\n",
  261.         commandname, logtype, name);
  262.     anywarns = ON;
  263.       }
  264.     }
  265.     else {
  266.       if (debug > 0)
  267.     fprintf(stderr, "F: Opening %s as %s\n", name, logtype);
  268. #ifndef NOPIPES
  269.       for (uncompressp = uncompresshead; uncompressp -> name[0] != '\0' &&
  270.        !(*ispipe); uncompressp = uncompressp -> next) {
  271.     if (wildmatch(name, uncompressp -> name, &w1, &w2)) {
  272.       fclose(f);
  273.       strcpy(command, uncompressp -> prefix);
  274.       strcat(command, " ");
  275.       strncat(command, name, MAXSTRINGLENGTH - strlen(command) - 1);
  276.       f = popen(command, "r");
  277.       *ispipe = ON;
  278.       if (debug > 0)
  279.         fprintf(stderr, "F:   Using %s to uncompress it\n",
  280.             uncompressp -> prefix);
  281.     }
  282.       }
  283. #endif
  284.     }
  285.   }
  286.  
  287.   return(f);
  288. }
  289.  
  290. int fcloselog(FILE *f, char *name, char logtype[12], flag ispipe)
  291. {     /* close it again */  /* logtype only used if NOPIPES off */
  292.   extern int pclose();
  293.  
  294.   extern int debug;
  295.  
  296. #ifndef NOPIPES
  297.   extern char *commandname;
  298.   extern flag warnq, anywarns;
  299. #endif
  300.  
  301.   int rc;
  302.  
  303.   if (debug > 0)
  304.     fprintf(stderr, "F: Closing %s\n", STREQ(name, "-")?"stdin":name);
  305.   if (!ispipe)
  306.     rc = fclose(f);    /* Not much can go wrong with fclose. I hope. */
  307. #ifndef NOPIPES
  308.   else if ((rc = pclose(f)) != 0 && warnq) {
  309.     fprintf(stderr, "%s: Warning: Problems uncompressing %s %s\n",
  310.         commandname, logtype, name);
  311.     anywarns = ON;
  312.   }
  313. #endif
  314.   return(rc);
  315. }
  316.  
  317. void int3printf(FILE *outf, int x, char sepchar, int fieldwidth)
  318.                     /* print +ve integer with separators every 3 digits */
  319. {                   /* assume fieldwidth is 0, or large enough */
  320.   extern int aq;
  321.  
  322.   int i = 1, len = 0;
  323.  
  324.   if (sepchar == '\0') {
  325.     if (fieldwidth == 0)
  326.       fprintf(outf, "%d", x);
  327.     else
  328.       fprintf(outf, "%*d", fieldwidth, x);
  329.   }
  330.  
  331.   else {
  332.     while (x / 1000 >= i) {   /* i * 1000 might overflow */
  333.       i *= 1000;     /* find how big x is, so we know where to start */
  334.       len += 4;
  335.     }
  336.  
  337.     if (fieldwidth == 0)
  338.       fprintf(outf, "%d", (x / i) % 1000);
  339.     else
  340.       fprintf(outf, "%*d", fieldwidth - len, (x / i) % 1000);
  341.                            /* now run down again, printing each clump */
  342.  
  343.     for ( i /= 1000; i >= 1; i /= 1000) {
  344.       if (aq == HTML)
  345.     htmlputc(sepchar, outf);
  346.       else
  347.     fprintf(outf, "%c", sepchar);
  348.       fprintf(outf, "%03d", (x / i) % 1000);
  349.     }
  350.   }
  351. }
  352.  
  353. void double3printf(FILE *outf, double x, char sepchar, int fieldwidth)
  354.                          /* the same, only with +ve INTEGER doubles */
  355. {
  356.   extern int aq;
  357.  
  358.   int i = 0;
  359.  
  360.   x += 0.1;   /* to make sure floors go in the right direction */
  361.  
  362.   if (x < 0.6) {
  363.     for (i = fieldwidth; i > 1; i--)
  364.       fprintf(outf, " ");
  365.     fprintf(outf, "0");
  366.   }
  367.  
  368.   else if (sepchar == '\0') {
  369.     if (fieldwidth == 0)
  370.       fprintf(outf, "%.0f", x);
  371.     else
  372.       fprintf(outf, "%*.0f", fieldwidth, x);
  373.   }
  374.  
  375.   else {
  376.  
  377.     while (x >= 1000) {
  378.       x /= 1000;
  379.       i++;
  380.     }
  381.  
  382.     if (i == 0) {
  383.       if (fieldwidth == 0)
  384.     fprintf(outf, "%d", (int)ROUND(x));
  385.       else
  386.     fprintf(outf, "%*d", fieldwidth - 4 * i, (int)ROUND(x));
  387.     }
  388.     else if (fieldwidth == 0)
  389.       fprintf(outf, "%d", (int)floor(x));
  390.     else
  391.       fprintf(outf, "%*d", fieldwidth - 4 * i, (int)floor(x));
  392.  
  393.     for ( ; i >= 1; i--) {
  394.       x -= (int)x;
  395.       x *= 1000;
  396.       if (aq == HTML)
  397.     htmlputc(sepchar, outf);
  398.       else
  399.     fprintf(outf, "%c", sepchar);
  400.       if (i == 1)
  401.     fprintf(outf, "%03d", (int)ROUND(x));
  402.       else
  403.     fprintf(outf, "%03d", (int)floor(x));
  404.     }
  405.   }
  406. }
  407.  
  408. void doublefprintf(FILE *outf, double x)
  409. {                 /* print a double in %f format without trailing zeros */
  410.   extern char decpoint;
  411.  
  412.   int prec = 0;
  413.   double d;
  414.  
  415.   /* first calculate how many decimal places we need */
  416.  
  417.   for (d = x - floor(x); d - floor(d + 0.000005) > 0.00001; d *= 10)
  418.     prec++;
  419.  
  420.   /* now print it */
  421.  
  422.   if (prec > 0) {
  423.     fprintf(outf, "%d", (int)floor(x));
  424.     fprintf(outf, "%c%0*d", decpoint, prec, (int)ROUND(d));
  425.   }
  426.   else
  427.     fprintf(outf, "%d", (int)ROUND(x));
  428. }
  429.  
  430. void *xmalloc(size_t size)
  431. {    /* the same as malloc, only checks for out of memory */
  432.  
  433.   extern char *commandname;
  434.   extern flag sq;
  435.  
  436.   void *answer;
  437.  
  438.   if ((answer = malloc(size)) == NULL) {
  439.     fprintf(stderr, "%s: Ran out of memory: cannot continue\n", commandname);
  440.     if (sq == ON)
  441.       fprintf(stderr, "  Try turning hostname counting off or using approximate host counting");
  442.     exit(ERR);
  443.   }
  444.  
  445.   return(answer);
  446. }
  447.  
  448. void *xcalloc(size_t nelem, size_t elsize)
  449. {    /* ditto calloc */
  450.  
  451.   extern char *commandname;
  452.   extern flag sq;
  453.  
  454.   void *answer;
  455.  
  456.   if ((answer = calloc(nelem, elsize)) == NULL) {
  457.     fprintf(stderr, "%s: Ran out of memory: cannot continue\n", commandname);
  458.     if (sq == ON)
  459.       fprintf(stderr, "  Try turning hostname counting off or using approximate host counting");
  460.     exit(ERR);
  461.   }
  462.  
  463.   return(answer);
  464. }
  465.  
  466. char *strtolower(char *string)
  467. {         /* convert a string to lower case */
  468.  
  469.   char *c;
  470.  
  471.   for (c = string ; *c != '\0'; c++)
  472.     *c = tolower(*c);
  473.  
  474.   return(string);
  475. }
  476.  
  477. flag strtolowerf(char *string)
  478. {         /* convert a string, return whether any changes required */
  479.  
  480.   char *c;
  481.   flag ans = FALSE;
  482.  
  483.   for (c = string ; *c != '\0'; c++) {
  484.     if (isupper(*c)) {
  485.       ans = TRUE;
  486.       *c = tolower(*c);
  487.     }
  488.   }
  489.  
  490.   return(ans);
  491. }
  492.  
  493. char *strtoupper(char *string)
  494. {         /* convert a string to upper case */
  495.  
  496.   char *c;
  497.  
  498.   for (c = string; *c != '\0'; c++)
  499.     *c = toupper(*c);
  500.  
  501.   return(string);
  502. }
  503.  
  504. int hoststrcmp(char *hostn1, char *hostn2)
  505. {   /* given two reversed hostnames, what is their "alphabetical" order? */
  506.  
  507.   char hostn1cpy[MAXSTRINGLENGTH], hostn2cpy[MAXSTRINGLENGTH];
  508.   char *part11, *part12, *part13, *part14, *part2;
  509.   int tempint1, tempint2;
  510.  
  511.   if (!isdigit(*hostn1)) {
  512.     if (isdigit(*hostn2))
  513.       return(-1);    /* all numbers come after all letters */
  514.     else
  515.       return(strcmp(hostn1, hostn2));   /* both non-numbers; usual alphabet */
  516.   }
  517.   else if (!isdigit(*hostn2))
  518.     return(1);
  519.   else  {
  520.     /* the difficult case; both numerical. Convert bits to numbers */
  521.     strcpy(hostn1cpy, hostn1);   /* because strtok destroys the string */
  522.     strcpy(hostn2cpy, hostn2);
  523.     part11 = strtok(hostn1cpy, ".");
  524.     part12 = strtok((char *)NULL, ".");
  525.     part13 = strtok((char *)NULL, ".");
  526.     part14 = strtok((char *)NULL, ".");
  527.  
  528.     part2 = strtok(hostn2cpy, ".");
  529.     tempint1 = atoi(part11);
  530.     tempint2 = atoi(part2);
  531.     if (tempint1 != tempint2)
  532.       return(tempint1 - tempint2);
  533.     else {
  534.       part2 = strtok((char *)NULL, ".");
  535.       if (part12 == NULL && part2 == NULL)
  536.     return(0);
  537.       else if (part12 == NULL)
  538.     return(-999);
  539.       else if (part2 == NULL)
  540.     return(999);
  541.       else {
  542.     tempint1 = atoi(part12);
  543.     tempint2 = atoi(part2);
  544.     if (tempint1 != tempint2)
  545.       return(tempint1 - tempint2);
  546.     else {
  547.       part2 = strtok((char *)NULL, ".");
  548.       if (part13 == NULL && part2 == NULL)
  549.         return(0);
  550.       else if (part13 == NULL)
  551.         return(-999);
  552.       else if (part2 == NULL)
  553.         return(999);
  554.       else {
  555.         tempint1 = atoi(part13);
  556.         tempint2 = atoi(part2);
  557.         if (tempint1 != tempint2)
  558.           return(tempint1 - tempint2);
  559.         else {
  560.           part2 = strtok((char *)NULL, ".");
  561.           if (part14 == NULL && part2 == NULL)
  562.         return(0);
  563.           else if (part14 == NULL)
  564.         return(-999);
  565.           else if (part2 == NULL)
  566.         return(999);
  567.           else {
  568.         tempint1 = atoi(part14);
  569.         tempint2 = atoi(part2);
  570.         if (tempint1 != tempint2)
  571.           return(tempint1 - tempint2);
  572.         else
  573.           return(0);
  574.           }
  575.         }
  576.       }
  577.     }
  578.       }
  579.     }
  580.   }
  581. }
  582.  
  583. /* Next, whether a host name is a numeric IP address */
  584. /* Actually we only check whether it consists only of digits & dots */
  585.  
  586. flag isnumeric(char *name)
  587. {
  588.   for ( ; *name != '\0'; name++)
  589.     if (!isdigit(*name) && *name != '.')
  590.       return(FALSE);
  591.   return(TRUE);
  592. }
  593.